package development.game;

import java.util.Vector;

import state.GameAlert;
import state.GameConstants;
import state.GameForm;
import state.GameGlobal;
import state.GameImage;
import state.Graphics;
import state.Key;
import state.TimerListener;
import state.component.BottomBar;
import state.component.Event;
import state.component.EventListener;
import state.component.GameMenu;
import state.font.FontManager;
import state.font.ImageText;
import state.socket.DataPackage;
import state.socket.DataReceiveListener;
import state.util.GameColor;
import state.util.Hashtable;
import state.util.ImageUtil;
import state.util.NumberUtil;
import state.util.array.BooleanArray;
import state.util.array.IntArray;
import state.util.array.StringArray;
import state.util.array.VectorArray;
import development.Constants;
import development.DrawUtils;
import development.Global;
import development.bean.Game;
import development.bean.PhomInfo;
import development.bean.TalaResultInfo;
import development.bean.User;
import development.group.FrmGroupListTableFreeUserChat;
import development.group.FrmGroupTableFreeUserFriend;
import development.socket.SocketClientUtil;

public class FrmTala extends GameForm implements TimerListener, EventListener, DataReceiveListener {
  private final int DELIVER_CARD_HEADER = 1;
  private final int FIRED_CARD_HEADER = 2;
  private final int BOC_BAI_HEADER = 3;
  private final int AN_BAI_HEADER = 4;
  private final int SEND_TOTAL_HEADER = 5;
  private final int INVALID_ACTION = 6;
  private final int VALID_ACTION = 7;
  private final int HA_PHOM_DONE_HEADER = 8;
  private final int HA_PHOM_HEADER = 9;
  private final int HOST_CARD_HEADER = 10;
  private final int TAKE_TURN = 11;
  private final int TURN_ORDER = 13;
  private final int RANDOM_CARD = 14;
  private final int HA_PHOM_XONG_HEADER = 15; // Ket thuc ha
  private final int HA_PHOM_SAI_HEADER = 16; // Phom ha khong hop le
  private final int HA_PHOM_TIMEOUT_HEADER = 17;
  private final int HOST_CARD_FAILED = 18;
  private final int HOST_CARD_DONE = 19;
  private final int HOST_CARD_SEND_HEADER = 20;
  private final int OUT_TABLE = 21;
  private final int FINAL_MONEY_HEADER = 22;
  private final int MONEY_CHANGE_NOTIFY_HEADER = 27;
  private static final int INIT_FOR_VIEW_USER_HEADER = 28;
  private static final int USER_VIEW_JOIN_HEADER = 29;

  private final int GET_CARD_STATE = 23;
  private final int FIRE_CARD_STATE = 24;
  private final int WAIT_STATE = 25;
  private final int HA_PHOM_STATE = 26;

  private final int CARD_DISTANCE = 22;
  private final int FIRED_CARD_DISTANCE = 15;
  private final int TURN_TIME_OUT = 30;
  private final int[][] TIME_LOCATION = new int[][]{{GameConstants.SCREEN_WIDTH / 2, 250}, {GameConstants.SCREEN_WIDTH - 50, GameConstants.SCREEN_HEIGHT / 2}, {GameConstants.SCREEN_WIDTH / 2, 50}, {50, GameConstants.SCREEN_HEIGHT / 2}};
  private final int[][] TIME_LOCATION_320x240 = new int[][]{{GameConstants.SCREEN_WIDTH / 2, 170}, {GameConstants.SCREEN_WIDTH - 50, GameConstants.SCREEN_HEIGHT / 2}, {GameConstants.SCREEN_WIDTH / 2, 50}, {50, GameConstants.SCREEN_HEIGHT / 2}};

  private final int[][][] USER_INFO_LOCATION_240x320 = new int[][][] 
   {
      {{140, 190}, {140, 0}},
      {{140, 190}, {140, 0}, {0, 140}},
      {{140, 190}, {190, 140}, {140, 0}, {0, 140}}
    };
 
  private final int[][][] USER_INFO_LOCATION_320x240 = new int[][][] 
   {
     {{180, 140}, {180, 0}},
     {{180, 140}, {180, 0}, {0, 100}},
     {{180, 140}, {280, 100}, {180, 0}, {0, 100}}
   };
  
//  private final int[][][] CHAT_LOCATION_240x320 = new int[][][] 
//    {
//      {{100, 190}, {80, 5}},
//      {{100, 190}, {80, 5}, {0, 140}},
//      {{100, 190}, {140, 140}, {80, 5}, {0, 140}}
//    };
//
//   private final int[][][] CHAT_LOCATION_320x240 = new int[][][] 
//    {
//      {{180, 140}, {140, 5}},
//      {{180, 140}, {140, 5}, {0, 100}},
//      {{180, 140}, {180, 100}, {140, 5}, {0, 100}}
//    };
 
  private final boolean[][] IS_INFO_RIGHT_TO_LEFT = new boolean[][]
    {
     {true, true},
     {true, true, false},
     {true, false, true, false}
    };
 
  private final int[][][] FINAL_POINT_LOCATION_240x320 = new int[][][]
  {
    {{105, 195}, {105, 65}},
    {{105, 195}, {170, 100}, {105, 65}},
    {{105, 195}, {170, 100}, {105, 65}, {40, 100}}
  };
  
  private final int[][][] FINAL_POINT_LOCATION_320x240 = new int[][][]
  {
    {{160, 148}, {150, 40}},
    {{160, 148}, {225, 105}, {150, 40}},
    {{160, 168}, {225, 105}, {150, 20}, {40, 105}}
  };
  
  private GameImage baiUpImage;
  private GameImage pointerImage;
  private GameImage[] cardImges;
  private GameImage numberBgImage;
  private GameImage[] ketQuaImage;
  private GameImage nhatImage;
  private GameImage uImage;
  private GameImage tableImage;

  private VectorArray userCards;
  private VectorArray firedCards;
  private VectorArray gotCards;
  private VectorArray phoms; // Phỏm
  private Vector selectedCardByUser;
  private Vector belongToPhoms;

  private int numberOfPlayer;
  private int state;
  private int messageIndex;
  private int movePointer;
  private int currentTurn;
  private int myIndex;
  private int lastFireCard;
  private ImageText text8;
  private ImageText text11;

  private boolean isShowingFinalResult;
  private BooleanArray isShowUserCard;
  private IntArray cardPoint;

  private int currentTimeIndex;
  private int currentTimeCount;
  private int count;
  private int remainCard;
  private boolean isSomeOneU;
  private String userJidU;

  private int timeShowResult;
  private BooleanArray isUserLeave;
  private BooleanArray isHaphom;
  private int[] timeDisplayMom;

  private boolean isCardsChange;
  private boolean isGuiBai;
  public Vector tableUsers; // Danh sách user trong bàn chơi hiện tại
  
  private int[][] userInfoLocation;
  private boolean[] isInfoRightToLeft;
  private int[][] finalPointLocation;
  
  private Hashtable rotatedCardCache;
  private Hashtable rotated90CardCache;
  private String[] cardOrder;
  
  private String moneyChangeMessage = "";
  private int moneyChangeIndex;
  private Hashtable resultInfos;
  private boolean isViewUser;
  private int showPointAndFinalResultImageTime;
  
  private static GameForm singleton;
  
  public static GameForm instance() {
    if (singleton == null) {
      singleton = new FrmTala();
    }
    return singleton;
  }
  
  public void init(Hashtable inputParameters) {
    isViewUser = false;
    belongToPhoms = new Vector();
    isUserLeave = BooleanArray.create(4);
    isHaphom = BooleanArray.create(4);
    timeDisplayMom = new int[4];
    for (int i = 0; i < 4; i++) {
      isUserLeave.array[i] = false;
      timeDisplayMom[i] = 0;
    }
    isCardsChange = false;
    isGuiBai = false;
    timeShowResult = 0;
    isSomeOneU = false;
    selectedCardByUser = new Vector();
    movePointer = 0;
    currentTurn = 0;
    messageIndex = -1;
    isShowingFinalResult = false;
    moneyChangeMessage = "";
    moneyChangeIndex = -1;
    showPointAndFinalResultImageTime = -1;

    // Khởi tạo các ảnh quân bài
    cardOrder = new String[] {"Bich", "Nhep", "Ro", "Co"};
    cardImges = new GameImage[52];

    ketQuaImage = new GameImage[4];
    ketQuaImage[0] = ImageUtil.getImage(Constants.NEW_IMAGE_CATEGORY, "mom.png");
    ketQuaImage[1] = ImageUtil.getImage(Constants.NEW_IMAGE_CATEGORY, "Nhi.png");
    ketQuaImage[2] = ImageUtil.getImage(Constants.NEW_IMAGE_CATEGORY, "Ba.png");
    ketQuaImage[3] = ImageUtil.getImage(Constants.NEW_IMAGE_CATEGORY, "Bet.png");
    nhatImage = ImageUtil.getImage(Constants.NEW_IMAGE_CATEGORY, "Nhat.png");
    uImage = ImageUtil.getImage(Constants.NEW_IMAGE_CATEGORY, "u.png");
    
    baiUpImage = ImageUtil.getImage(Constants.CARD_IMAGE_CATEGORY, "Bai_MSau.png");
    GameImage backButtonImage = ImageUtil.getImage(Constants.CARD_IMAGE_CATEGORY, "button_back.png");
    pointerImage = ImageUtil.rotate(backButtonImage, 90);
    numberBgImage = ImageUtil.getImage(Constants.NEW_IMAGE_CATEGORY, "Nen_So.png");
    tableImage = ImageUtil.getImage(Constants.CARD_IMAGE_CATEGORY, "bg_Danh-bai.png");

    text8 = FontManager.getFont(FontManager.FONT_SIZE_8);
    text11 = FontManager.getFont(FontManager.FONT_SIZE_11);
    rotatedCardCache = new Hashtable();
    rotated90CardCache = new Hashtable();

    // Init menu
    GameMenu menu = new GameMenu(null, new String[]{"Chơi tiếp", "Sắp xếp", "Thoát"}, 3, this, Constants.MENU_STYLE, GameConstants.SCREEN_WIDTH - 120, GameConstants.SCREEN_HEIGHT - 42);
    menu.setOpenChildMenuToRight(false);
    BottomBar bottomBar = DrawUtils.getBottomBar(_manager);
    bottomBar.setRightMenu("Menu", menu);
    
    setTimerListener(this);
    DataPackage dataPackage = Game.createGamePackage(TURN_ORDER);
    Global.gameActionClient.write(dataPackage);
    resultInfos = new Hashtable();
    _manager.enableTouchPad();
  }
  
  private void prepareDrawLocation(int numberOfPlayer1) {
    if (GameConstants.IS_240x320_SCREEN) {
      userInfoLocation = USER_INFO_LOCATION_240x320[numberOfPlayer1 - 2];
      finalPointLocation = FINAL_POINT_LOCATION_240x320[numberOfPlayer1 - 2];
    } else {
      userInfoLocation = USER_INFO_LOCATION_320x240[numberOfPlayer1 - 2];
      finalPointLocation = FINAL_POINT_LOCATION_320x240[numberOfPlayer1 - 2];
    }
    
    // TODO: disable chat of game Tala
//    Global.initChatComponent(CHAT_LOCATION_240x320[numberOfPlayer1 - 2], CHAT_LOCATION_320x240[numberOfPlayer1 - 2]);
    isInfoRightToLeft = IS_INFO_RIGHT_TO_LEFT[numberOfPlayer1 - 2];
    
  }
  
  private void initForViewUser(DataPackage dataPackage) {
    // Get fired card
    int numberOfUser = dataPackage.nextInt();
    for (int i = 0; i < numberOfUser; i++) {
      String username = dataPackage.nextString();
      int userIndex = getUserIndex(username);
      int numberOfCard = dataPackage.nextInt();
      for (int j = 0; j < numberOfCard; j++) {
        firedCards.array[userIndex].addElement(new Integer(dataPackage.nextInt()));
      }
    }
    
    // Get gotCards
    numberOfUser = dataPackage.nextInt();
    for (int i = 0; i < numberOfUser; i++) {
      String username = dataPackage.nextString();
      int userIndex = getUserIndex(username);
      int numberOfCard = dataPackage.nextInt();
      for (int j = 0; j < numberOfCard; j++) {
        gotCards.array[userIndex].addElement(new Integer(dataPackage.nextInt()));
      }
    }
    
    // Init card for all other user
    for (int i = 0; i < tableUsers.size(); i++) {
      User user = (User) tableUsers.elementAt(i);
      if (!user.isViewUser()) {
        int index = getUserIndex(user.getName());
        userCards.array[index].addElement(new Integer(0));
      }
    }
    
    // Init for chat
    // TODO: disable chat of game Tala
//    SocketClientUtil.joinChatRoom(CHAT_LOCATION_240x320[tableUsers.size() - 2], CHAT_LOCATION_320x240[tableUsers.size() - 2]);
  }
  
  private VectorArray expandArray(VectorArray oldArray) {
    VectorArray newArray = VectorArray.create(oldArray.len() + 1);
    for (int i = 0; i < oldArray.len(); i++) {
      newArray.array[i] = oldArray.array[i];
    }
    newArray.array[newArray.len() - 1] = new Vector();
    return newArray;
  }
  
  private IntArray expandArray(IntArray oldArray) {
    IntArray newArray = IntArray.create(oldArray.len() + 1);
    for (int i = 0; i < oldArray.len(); i++) {
      newArray.array[i] = oldArray.array[i];
    }
    return newArray;
  }
  
  private BooleanArray expandArray(BooleanArray oldArray) {
    BooleanArray newArray = BooleanArray.create(oldArray.len() + 1);
    for (int i = 0; i < oldArray.len(); i++) {
      newArray.array[i] = oldArray.array[i];
    }
    return newArray;
  }
  
  private void onUserViewJoin(DataPackage dataPackage) {
    String viewUserName = dataPackage.nextString();
    User userView = getUserByName(viewUserName);
    if (userView == null) {
      userView = new User(viewUserName);
      Global.tableUsers.addElement(userView);
    }
    
    if (!tableUsers.contains(userView)) {
      tableUsers.addElement(userView);
      
      numberOfPlayer = tableUsers.size();
      prepareDrawLocation(numberOfPlayer);
      myIndex = getUserIndex(Global.currentUser.getName());
      
      userCards = expandArray(userCards);
      firedCards = expandArray(firedCards);
      gotCards = expandArray(gotCards);
      phoms = expandArray(phoms);
      isShowUserCard = expandArray(isShowUserCard);
      cardPoint = expandArray(cardPoint);
    } else {
      int viewUserIndex = 0;
      for (int i = 0; i < tableUsers.size(); i++) {
        User user = (User) tableUsers.elementAt(i);
        if (user.getName().equals(viewUserName)) {
          viewUserIndex = i;
          break;
        }
      }
      isUserLeave.array[viewUserIndex] = false;
      isShowUserCard.array[viewUserIndex] = false;
      userCards.array[viewUserIndex].removeAllElements();
    }
  }

  public void onRecieveData(DataPackage dataPackage) {
    int header = dataPackage.getHeader();
    switch (header) {
    case INIT_FOR_VIEW_USER_HEADER:
      initForViewUser(dataPackage);
      break;
    case USER_VIEW_JOIN_HEADER:
      onUserViewJoin(dataPackage);
      break;
    case DELIVER_CARD_HEADER:
      // Nhận quân bài
      int index = dataPackage.nextInt();
      for (int i = 0; i < index; i++) {
        userCards.array[myIndex].addElement(new Integer(dataPackage.nextInt()));
      }
      sapXepTangDanTheoCaNgang(userCards.array[myIndex]);
      // Add quân bài chưa biết vào cho các user khác
      for (int i = 0; i < userCards.len(); i++) {
        if (userCards.array[i].size() == 0) {
          for (int j = 0; j < 9; j++) {
            userCards.array[i].addElement(new Integer(0));
          }
        }
      }
      break;
    case TURN_ORDER:
      Vector userListTmp = new Vector();
      int sizeUser = dataPackage.nextInt();
      for (int i = 0; i < sizeUser; i++) {
        String userName = dataPackage.nextString();
        User nextUser = getUserByName(userName);
        if (nextUser != null) {
          userListTmp.addElement(nextUser);
        }
      }
      tableUsers = userListTmp;
      numberOfPlayer = tableUsers.size();
      processTurnOrder();
      break;
    case TAKE_TURN:
      String userName = dataPackage.nextString();
      if (userName.equals(Global.currentUser.getName())) {
        if (userCards.array[myIndex].size() == 10) {
          state = FIRE_CARD_STATE;
        } else {
          state = GET_CARD_STATE;
        }
      }
      currentTimeIndex = getUserIndex(userName);
      currentTimeCount = TURN_TIME_OUT;
      count = 0;
      break;
    case FIRED_CARD_HEADER:
      int card = dataPackage.nextInt();
      String fromUser = dataPackage.nextString();
      if (fromUser.equals(Global.currentUser.getName())) {
        return;
      }
      int userIndex = getUserIndex(fromUser);
      firedCards.array[userIndex].addElement(new Integer(card));
      lastFireCard = card;
      currentTimeCount = -1;
      break;
    case BOC_BAI_HEADER:
      String userBoc = dataPackage.nextString();
      if (Global.currentUser.getName().equals(userBoc)) {
        int cardBoc = dataPackage.nextInt();
        userCards.array[myIndex].addElement(new Integer(cardBoc));
        state = FIRE_CARD_STATE;
      }
      remainCard--;
      break;
    case AN_BAI_HEADER:
      dataPackage.nextInt(); // Card ăn
      String fromUserBiAn = dataPackage.nextString();
      String fromUserAn = dataPackage.nextString();
      if (fromUserAn.equals(Global.currentUser.getName())) {
        return;
      }
      int indexBiAn = getUserIndex(fromUserBiAn);
      int indexAn = getUserIndex(fromUserAn);
      gotCards.array[indexAn].addElement(firedCards.array[indexBiAn].elementAt(firedCards.array[indexBiAn].size() - 1));
      userCards.array[indexAn].removeElementAt(0);
      firedCards.array[indexBiAn].removeElementAt(firedCards.array[indexBiAn].size() - 1);
      sanBai(indexAn, indexBiAn);
      break;
    case HA_PHOM_SAI_HEADER:
      messageIndex = 6;
      break;
    case HA_PHOM_DONE_HEADER:
      movePointer = 0;
      int numberOfPhom = dataPackage.nextInt();
      Vector tmpPhom = new Vector();
loop1:for (int i = 0; i < numberOfPhom; i++) {
        PhomInfo phomInfo = new PhomInfo();
        int phomSize = dataPackage.nextInt();
        for (int j = 0; j < phomSize; j++) {
          int cardPhom = dataPackage.nextInt();
          if (belongToPhoms.contains(new Integer(cardPhom))) {
            continue loop1;
          }
          phomInfo.addCard(cardPhom);
          belongToPhoms.addElement(new Integer(cardPhom));
          removeElementByValue(userCards.array[myIndex], cardPhom);
        }
        tmpPhom.addElement(phomInfo);
      }
      String userHa = dataPackage.nextString();

      int indexHa = getUserIndex(userHa);
      for (int i = 0; i < tmpPhom.size(); i++) {
        phoms.array[indexHa].addElement(tmpPhom.elementAt(i));
      }
      if (indexHa == myIndex) {
        isGuiBai = true;
      }
      isHaphom.array[indexHa] = true;
      currentTimeCount = TURN_TIME_OUT;
      selectedCardByUser.removeAllElements();
      state = FIRE_CARD_STATE;
      break;
    case HA_PHOM_HEADER:
      int sizeHaPhom = dataPackage.nextInt();
      movePointer = 0;
      Vector tmpPhomHaPhom = new Vector();
      for (int i = 0; i < sizeHaPhom; i++) {
        int sizePhom1 = dataPackage.nextInt();
        for (int j = 0; j < sizePhom1; j++) {
          int cardHaPhom = dataPackage.nextInt();
          tmpPhomHaPhom.addElement(new Integer(cardHaPhom));
        }
      }
      String userHaPhom = dataPackage.nextString();
      int indexHaPhom = getUserIndex(userHaPhom);
      if (indexHaPhom == myIndex) {
        selectedCardByUser.removeAllElements();
        for (int i = 0; i < tmpPhomHaPhom.size(); i++) {
          selectedCardByUser.addElement(tmpPhomHaPhom.elementAt(i));
        }
        currentTimeCount = TURN_TIME_OUT;
        currentTimeIndex = getUserIndex(userHaPhom);
        if (selectedCardByUser.size() > 0) {
          state = HA_PHOM_STATE;
        } else {
          DataPackage haPhomXongPackage = Game.createGamePackage(HA_PHOM_XONG_HEADER);
          haPhomXongPackage.putInt(0);
          Global.gameActionClient.write(haPhomXongPackage);
        }
      }
      break;
    case MONEY_CHANGE_NOTIFY_HEADER:
      String username1 = dataPackage.nextString();
      int changedMoney1 = dataPackage.nextInt();
      if (username1.equals(Global.currentUser.getName())) {
        if (changedMoney1 > 0) {
          moneyChangeMessage = "Thưởng " + changedMoney1 + " gold";
        } else {
          moneyChangeMessage = "Trừ " + Math.abs(changedMoney1) + " gold";
        }
        moneyChangeIndex = 0;
      }
      break;
    case FINAL_MONEY_HEADER:
      String username = dataPackage.nextString();
      int finalMoney = dataPackage.nextInt();
      TalaResultInfo result = (TalaResultInfo) resultInfos.get(username);
      if (result == null) {
        result = new TalaResultInfo(username);
        resultInfos.put(username, result);
      }
      result.setFinalMoney(finalMoney);
      
      if (Global.currentUser.getName().equals(username)) {
        if (finalMoney > 0) {
          moneyChangeMessage = "Thưởng " + finalMoney + " gold";
        } else {
          moneyChangeMessage = "Trừ " + Math.abs(finalMoney) + " gold";
        }
        moneyChangeIndex = 0;
      }
      break;
    case SEND_TOTAL_HEADER:
      String userNameKetQua = dataPackage.nextString();
      int result1 = dataPackage.nextInt();
      int result2 = dataPackage.nextInt();
      int userIndexKetQua = getUserIndex(userNameKetQua);
      int point = result1;
      int rank = numberOfPlayer - 1;
      if (point == 0) { // Nếu người chơi ù
        rank = result2;
        isSomeOneU = true;
        userJidU = userNameKetQua;
      } else if (point == -1) {
        int check = dataPackage.nextInt();
        if (check == 0) { // Nếu là bét do ù
          rank = 4;
        } else { // nếu là móm
          rank = -1;
          int lengthCard = check;
          userCards.array[userIndexKetQua].removeAllElements();
          for (int t = 0; t < lengthCard; t++) {
            int cardTotal = dataPackage.nextInt();
            userCards.array[userIndexKetQua].addElement(new Integer(cardTotal));
          }
        }
      } else {
        rank = result2;
        int lengthCard = dataPackage.nextInt();
        userCards.array[userIndexKetQua].removeAllElements();
        for (int t = 0; t < lengthCard; t++) {
          int cardTotal = dataPackage.nextInt();
          userCards.array[userIndexKetQua].addElement(new Integer(cardTotal));
        }
      }
      
      TalaResultInfo resultInfo = (TalaResultInfo) resultInfos.get(userNameKetQua);
      if (resultInfo == null) {
        resultInfo = new TalaResultInfo(userNameKetQua);
        resultInfos.put(userNameKetQua, resultInfo);
      }

      if (rank < numberOfPlayer) {
        resultInfo.setRank(rank);
        resultInfo.setFinalPoint(point);
      }
      gotCards.array[userIndexKetQua].removeAllElements();
      isShowUserCard.array[userIndexKetQua] = true;
      isShowingFinalResult = true;
      currentTimeCount = -1;
      showPointAndFinalResultImageTime = 0;
      
      int m = 0;
l1:   while(m < userCards.array[userIndexKetQua].size()) {
        for (int j = 0; j < belongToPhoms.size(); j++) {
          if (userCards.array[userIndexKetQua].elementAt(m).equals(belongToPhoms.elementAt(j))) {
            userCards.array[userIndexKetQua].removeElementAt(m);
            continue l1;
          }
        }
        m++;
      }
      break;
    case HOST_CARD_FAILED:
      messageIndex = 7;
      break;
    case HOST_CARD_DONE:
      String userHost1 = dataPackage.nextString();
      int cardHost = dataPackage.nextInt();
      dataPackage.nextInt(); // indexPhom
      String userHost2 = dataPackage.nextString();
      int user1Index = getUserIndex(userHost1);
      int user2Index = getUserIndex(userHost2);

      // Thêm cây gửi vào phỏm của người chơi đã hạ
      for (int i = 0; i < phoms.array[user2Index].size(); i++) {
        PhomInfo phom = (PhomInfo) phoms.array[user2Index].elementAt(i);
        Vector temp1 = new Vector();
        for (int j = 0; j < phom.size(); j++) {
          temp1.addElement(new Integer(phom.getCard(j)));
        }
        if (isCaNgang(temp1, cardHost)) {
          phom.addCard(cardHost);
          break;
        } else if (isCaDoc(temp1)) {
          phom.addCard(cardHost);
          break;
        }
      }

      // Bỏ cây đã gửi ra khỏi bài của người chơi đã gửi bài
      if (userHost1.equals(Global.currentUser.getName())) {
        removeElementByValue(userCards.array[myIndex], cardHost);
        removeElementByValue(selectedCardByUser, cardHost);
      } else {
        userCards.array[user1Index].removeElementAt(0);
      }
      break;
    case HOST_CARD_HEADER:
      String userHost = dataPackage.nextString();
      int indexUser = getUserIndex(userHost);
      if (indexUser == myIndex) {
        isGuiBai = true;
        selectedCardByUser.removeAllElements();
        int sizeHot = dataPackage.nextInt();
        for (int t = 0; t < sizeHot; t++) {
          selectedCardByUser.addElement(new Integer(dataPackage.nextInt()));
        }
      }
      break;
    case RANDOM_CARD:
      int cardRandom = dataPackage.nextInt();
      lastFireCard = cardRandom;
      sendDanhBai(cardRandom);
      break;
    case VALID_ACTION:
      int headerAction = dataPackage.nextInt();
      switch (headerAction) {
      case AN_BAI_HEADER:
        dataPackage.nextInt(); // latestFiredCard
        String userBiAn = dataPackage.nextString();
        System.out.println(">>>>userBiAn: " + userBiAn);
        dataPackage.nextString(); // userAn
        int before = getUserIndex(userBiAn);
        userCards.array[myIndex].addElement(new Integer(lastFireCard));
        gotCards.array[myIndex].addElement(new Integer(lastFireCard));
        firedCards.array[before].removeElementAt(firedCards.array[before].size() - 1);
        selectedCardByUser.removeAllElements();
        state = FIRE_CARD_STATE;
        sanBai(myIndex, before);
        break;
      case FIRED_CARD_HEADER:
        firedCards.array[myIndex].addElement(new Integer(lastFireCard));
        removeElementByValue(userCards.array[myIndex], lastFireCard);
        if (movePointer > userCards.array[myIndex].size() - 1) {
          movePointer = userCards.array[myIndex].size() - 1;
        }
        selectedCardByUser.removeAllElements();
        currentTurn = currentTurn + 1;
        if (currentTurn > numberOfPlayer - 1) {
          currentTurn = 0;
        }
        state = WAIT_STATE;
        break;
      }
      break;
    case INVALID_ACTION:
      int headerInAction = dataPackage.nextInt();
      switch (headerInAction) {
      case AN_BAI_HEADER:
        messageIndex = 0;
        break;
      case FIRED_CARD_HEADER:
        messageIndex = 1;
        break;
      }
      break;
    case OUT_TABLE:
      String userOut = dataPackage.nextString();
      if (!userOut.equals(Global.currentUser.getName())) {
        for (int i = 0; i < tableUsers.size(); i++) {
          User userRemove = (User) tableUsers.elementAt(i);
          if (userRemove.getName().equals(userOut)) {
            isUserLeave.array[i] = true;
          }
        }
      }
      break;
    }
  }
  
  private void processTurnOrder() {
    prepareDrawLocation(numberOfPlayer);
    myIndex = getUserIndex(Global.currentUser.getName());
    numberOfPlayer = tableUsers.size();
    state = WAIT_STATE;
    currentTimeIndex = -1;
    currentTimeCount = -1;
    
    switch (numberOfPlayer) {
    case 2:
      remainCard = 7;
      break;
    case 3:
      remainCard = 11;
      break;
    case 4:
      remainCard = 15;
      break;
    }

    userCards = VectorArray.create(numberOfPlayer);
    firedCards = VectorArray.create(numberOfPlayer);
    gotCards = VectorArray.create(numberOfPlayer);
    phoms = VectorArray.create(numberOfPlayer);
    isShowUserCard = BooleanArray.create(numberOfPlayer);
    cardPoint = IntArray.create(numberOfPlayer);
    for (int i = 0; i < numberOfPlayer; i++) {
      userCards.array[i] = new Vector();
      firedCards.array[i] = new Vector();
      gotCards.array[i] = new Vector();
      phoms.array[i] = new Vector();
      cardPoint.array[i] = -1;
      isShowUserCard.array[i] = false;
    }
  }

  private User getUserByName(String userName) {
    for (int i = 0; i < Global.tableUsers.size(); i++) {
      if (userName.equals(((User) Global.tableUsers.elementAt(i)).getName())) {
        return (User) Global.tableUsers.elementAt(i);
      }
    }
    return null;
  }

  private int getUserIndex(String userName) {
    for (int i = 0; i < tableUsers.size(); i++) {
      if (userName.equals(((User) tableUsers.elementAt(i)).getName())) {
        return i;
      }
    }
    return -1;
  }

  /**
   * Sau khi 1 cây bài bị ăn thì cần kiểm tra và san những lá bài đã đánh cho
   * đều
   */
  private void sanBai(int index, int beforeIndex) {
    int tmp = index;
    Object changeCard;
    for (int i = 0; i < numberOfPlayer; i++) {
      if (firedCards.array[beforeIndex].size() < firedCards.array[tmp].size()) {
        changeCard = firedCards.array[tmp].lastElement();
        firedCards.array[beforeIndex].addElement(changeCard);
        firedCards.array[tmp].removeElement(changeCard);
        break;
      } else {
        tmp = behindUser(tmp);
      }
    }
  }

  private int behindUser(int index) {
    int behind = 0;
    if (index == numberOfPlayer - 1) {
      behind = 0;
    } else {
      behind = (index + 1) % numberOfPlayer;
    }
    while (isUserLeave.array[behind]) {
      behind = (behind + 1) % numberOfPlayer;
    }
    return behind;
  }

  private int getRealIndex(int position) {
    position = myIndex + position;
    position = position % numberOfPlayer;
    return position;
  }

  private int getDrawIndex(int index) {
    index = (index - myIndex + numberOfPlayer) % numberOfPlayer;
    return index;
  }

  public void keyReleased(int keyCode) {
    if (isShowingFinalResult) {
      if (keyCode == Key.FIRE) {
        GameGlobal.nextState(FrmGroupTableFreeUserFriend.instance(), null);
      }

      if (keyCode == Key.SOFT_RIGHT) {
        SocketClientUtil.leaveTableRequest();
        GameGlobal.nextState(FrmGroupListTableFreeUserChat.instance(), null);
      }
      return;
    }

    if (!Key.isCommandKey) {
      if (Global.chatComponent != null) {
        Global.chatComponent.setShowInputChatMessageTextField(true);
        Global.chatComponent.keyReleased(keyCode);
      }
      return;
    }
    
    // If chat box already show
    if (Global.isShowedInputChatBox()) {
      switch (keyCode) {
      case Key.SOFT_LEFT:
        Global.hideInputChatBox();
        break;
      case Key.FIRE:
        SocketClientUtil.sendMessage(Global.chatComponent.getCurrentRoomId(), Global.chatComponent.getChatTextField().getText());
        Global.hideInputChatBox();
        break;
      case Key.SOFT_RIGHT:
        Global.chatComponent.getChatTextField().deleteLastChar();
        GameMenu rightMenu = DrawUtils.getBottomBar(_manager).getRightMenu();
        if (rightMenu != null) {
          rightMenu.hide();
        }
        break;
      }
      return;
    }
    
    switch (keyCode) {
    case Key.LEFT:
      if (isViewUser) {
        return;
      }
      int move = movePointer;
      movePointer--;
      if (movePointer < 0) {
        movePointer = userCards.array[myIndex].size() - 1;
      }
      messageIndex = -1;

      if (isCardsChange) {
        Object baiTemp = userCards.array[myIndex].elementAt(move);
        userCards.array[myIndex].setElementAt(userCards.array[myIndex].elementAt(movePointer), move);
        userCards.array[myIndex].setElementAt(baiTemp, movePointer);
      }
      break;
    case Key.RIGHT:
      if (isViewUser) {
        return;
      }
      int move1 = movePointer;
      movePointer++;
      if (movePointer > userCards.array[myIndex].size() - 1) {
        movePointer = 0;
      }
      messageIndex = -1;
      if (isCardsChange) {
        Object baiTemp = userCards.array[myIndex].elementAt(move1);
        userCards.array[myIndex].setElementAt(userCards.array[myIndex].elementAt(movePointer), move1);
        userCards.array[myIndex].setElementAt(baiTemp, movePointer);
      }
      break;
    case Key.SOFT_LEFT:
      if (isViewUser) {
        return;
      }
      switch (state) {
      case GET_CARD_STATE:
        DataPackage bocBaiPackage = Game.createGamePackage(BOC_BAI_HEADER);
        Global.gameActionClient.write(bocBaiPackage);
        break;
      case FIRE_CARD_STATE:
        if (isGuiBai) {
          if (selectedCardByUser.size() > 0) {
            DataPackage hostCardPackage = Game.createGamePackage(HOST_CARD_SEND_HEADER);
            hostCardPackage.putInt(selectedCardByUser.size());
            for (int i = 0; i < selectedCardByUser.size(); i++) {
              hostCardPackage.putInt(getInt(selectedCardByUser, i));
            }
            Global.gameActionClient.write(hostCardPackage);
          }
        }
        break;
      }
      break;
    case Key.FIRE:
      if (isViewUser) {
        return;
      }
      messageIndex = -1;
      if (state == HA_PHOM_STATE) {
        DataPackage haPhomXongPackage = Game.createGamePackage(HA_PHOM_XONG_HEADER);
        haPhomXongPackage.putInt(selectedCardByUser.size());
        for (int i = 0; i < selectedCardByUser.size(); i++) {
          haPhomXongPackage.putInt(getInt(selectedCardByUser, i));
        }
        Global.gameActionClient.write(haPhomXongPackage);
      }

      switch (state) {
      case GET_CARD_STATE:
        // AN_BAI_HEADER:2:0405
        if (selectedCardByUser.size() > 0) {
          DataPackage anBaiPackage = Game.createGamePackage(AN_BAI_HEADER);
          anBaiPackage.putInt(selectedCardByUser.size());
          for (int i = 0; i < selectedCardByUser.size(); i++) {
            anBaiPackage.putInt(getInt(selectedCardByUser, i));
          }
          Global.gameActionClient.write(anBaiPackage);
        } else {
          messageIndex = 4; // Thông báo là cần phải nhấc bài lên để ăn quân
        }
        break;
      case FIRE_CARD_STATE:
        int cardValue = getInt(userCards.array[myIndex], movePointer);
        lastFireCard = cardValue;
        int index = getIndexByValue(selectedCardByUser, cardValue);
        if (index > -1) {
          sendDanhBai(cardValue);
        } else {
          messageIndex = 5; // Thông báo là cần phải nhấc bài lên để đánh
        }
        break;
      }
      break;
    case Key.UP:
      if (isViewUser) {
        return;
      }
      messageIndex = -1;
      switch (state) {
      case GET_CARD_STATE:
      case FIRE_CARD_STATE:
      case WAIT_STATE:
      case HA_PHOM_STATE:
        if (!isCardsChange) {
          int card = NumberUtil.parseInt(String.valueOf(userCards.array[myIndex].elementAt(movePointer)));
          if (getIndexByValue(gotCards.array[myIndex], card) == -1 || state == HA_PHOM_STATE) {
            selectedCardByUser.addElement(userCards.array[myIndex].elementAt(movePointer));
          }
        }
        break;
      }
      isCardsChange = false;
      break;
    case Key.DOWN:
      if (isViewUser) {
        return;
      }
      messageIndex = -1;
      if (getIndexByValue(selectedCardByUser, getInt(userCards.array[myIndex], movePointer)) <= -1) {
        isCardsChange = true;
      }
      switch (state) {
      case GET_CARD_STATE:
      case FIRE_CARD_STATE:
      case WAIT_STATE:
      case HA_PHOM_STATE:
        removeElementByValue(selectedCardByUser, getInt(userCards.array[myIndex], movePointer));
        break;
      }
      break;
    }
  }

  private int getInt(Vector vector, int index) {
    if (index > vector.size() - 1) {
      return 0;
    }
    return NumberUtil.parseInt(String.valueOf(vector.elementAt(index)));
  }

  private int getIndexByValue(Vector vector, int value) {
    for (int i = 0; i < vector.size(); i++) {
      if (getInt(vector, i) == value) {
        return i;
      }
    }
    return -1;
  }

  private void removeElementByValue(Vector vector, int value) {
    for (int i = 0; i < vector.size(); i++) {
      if (getInt(vector, i) == value) {
        vector.removeElementAt(i);
        return;
      }
    }
  }

  private void sendDanhBai(int firedCard) {
    DataPackage fireCardPackage = Game.createGamePackage(FIRED_CARD_HEADER);
    fireCardPackage.putInt(firedCard);
    Global.gameActionClient.write(fireCardPackage);
  }

  public void doTask() {
    count = (count + 1) % 1000;
    if (count % 10 == 0) {
      if (currentTimeCount > -1) {
        currentTimeCount--;
        if ((currentTimeCount == 3) && (currentTimeIndex == myIndex)) {
          if (state == GET_CARD_STATE) {
            DataPackage bocBaiPackage = Game.createGamePackage(BOC_BAI_HEADER);
            Global.gameActionClient.write(bocBaiPackage);
          }
        }
        if ((currentTimeCount == -1) && (currentTimeIndex == myIndex)) {
          if (state == HA_PHOM_STATE) {
            DataPackage haPhomTimoutPackage = Game.createGamePackage(HA_PHOM_TIMEOUT_HEADER);
            Global.gameActionClient.write(haPhomTimoutPackage);
          } else {
            DataPackage randomCardPackage = Game.createGamePackage(RANDOM_CARD);
            Global.gameActionClient.write(randomCardPackage);
          }
        }
      }
    }

    if (isShowingFinalResult) {
      timeShowResult++;
      if (showPointAndFinalResultImageTime > -1) {
        showPointAndFinalResultImageTime++;
      }
    }
    
    if (moneyChangeIndex > -1) {
      moneyChangeIndex++;
      if (moneyChangeIndex > 50) {
        moneyChangeIndex = -1;
      }
    }
    
    if (showPointAndFinalResultImageTime > 50) {
      showPointAndFinalResultImageTime = -1;
    }
    
    if (timeShowResult == 300) {
      GameGlobal.nextState(FrmGroupTableFreeUserFriend.instance(), null);
      return;
    }
    for (int i = 0; i < 4; i++) {
      if (isHaphom.array[i] && timeDisplayMom[i] <= 100) {
        timeDisplayMom[i]++;
      }
    }
  }

  public void draw(Graphics g) {
    DrawUtils.drawBackground(g);
    g.drawImage(tableImage, Constants.SCREEN_WIDTH / 2, (Constants.SCREEN_HEIGHT - 25) / 2, Constants.CENTER_ANCHOR);
    
    // Vẽ bài còn lại trên bàn
    g.drawImage(baiUpImage, GameConstants.SCREEN_WIDTH / 2, (GameConstants.SCREEN_HEIGHT - 25) / 2, GameConstants.CENTER_ANCHOR);
    text8.drawString2(g, String.valueOf(remainCard), GameColor.WHITE_CODE, GameConstants.SCREEN_WIDTH / 2, (GameConstants.SCREEN_HEIGHT - 25) / 2, GameConstants.CENTER_ANCHOR);
    
    if (GameConstants.IS_240x320_SCREEN) {
      drawUserInfo(g);
      drawFiredCard(g);
      drawPhom(g);
      drawUserCards(g, TIME_LOCATION);
    } else {
      drawUserInfo(g);
      drawFiredCard320x240(g);
      drawPhom320x240(g);
      drawUserCards(g, TIME_LOCATION_320x240);
    }
    
    drawCommand(g);
    Global.drawChat(g);
    drawMessage(g);
    drawMoneyChangeNotification(g);
    
    if (isShowingFinalResult) {
      if (GameConstants.IS_240x320_SCREEN) {
        drawFinalResult(g, TIME_LOCATION);
      } else {
        drawFinalResult(g, TIME_LOCATION_320x240);
      }
    }
  }

  private void drawFinalResult(Graphics g, int[][] timeLocation) {
    // Vẽ ảnh hiệu ứng thứ hạng
    for (int i = 0; i < numberOfPlayer; i++) {
      if (isUserLeave.array[i]) {
        continue;
      }
      int index = getDrawIndex(i);
      User user = (User) tableUsers.elementAt(i);
      TalaResultInfo resultInfo = (TalaResultInfo) resultInfos.get(user.getName());
      if (resultInfo == null) {
        continue;
      }
      
      if (!isSomeOneU && (resultInfo.getFinalPoint() > 0)) {
        // Draw final point
        String finalPoint = String.valueOf(resultInfo.getFinalPoint());
        g.setColor(0x3CA446);
        int length = text11.stringWidth(finalPoint + " điểm");
        g.fillRect(finalPointLocation[index][0], finalPointLocation[index][1], length + 4, 20);
        text11.setBold(true);
        text11.drawString2(g, finalPoint + " điểm", GameColor.WHITE_CODE, finalPointLocation[index][0], finalPointLocation[index][1] - 5, Constants.TOP_LEFT_ANCHOR);
        text11.setBold(false);
      }
      
      // Get index to draw result image
      int drawIndex = index;
      if (numberOfPlayer == 2) {
        if (index == 1) {
          drawIndex = 2;
        }
      } else if (numberOfPlayer == 3) {
        if (index > 0) {
          drawIndex++;
        }
      }
      
      // Draw result Image
      if (isSomeOneU) { // nếu người đứng nhất ù
        int uUserIndex = getUserIndex(userJidU);
        if (uUserIndex == i) {
          g.drawImage(uImage, timeLocation[drawIndex][0], timeLocation[drawIndex][1], GameConstants.CENTER_ANCHOR);
        } else {
          g.drawImage(ketQuaImage[3], timeLocation[drawIndex][0], timeLocation[drawIndex][1], GameConstants.CENTER_ANCHOR);
        }
      } else {
        int rank = resultInfo.getRank();
        if (rank > 0) {
          if (showPointAndFinalResultImageTime > -1) {
            g.drawImage(ketQuaImage[rank], timeLocation[drawIndex][0], timeLocation[drawIndex][1], GameConstants.CENTER_ANCHOR);
          }
        } else if (rank == 0) {
          if (showPointAndFinalResultImageTime > -1) {
            g.drawImage(nhatImage, timeLocation[drawIndex][0], timeLocation[drawIndex][1], GameConstants.CENTER_ANCHOR);
          }
        } else {
          // Trường hợp rank < 0 --> móm
          g.drawImage(ketQuaImage[0], timeLocation[drawIndex][0], timeLocation[drawIndex][1], GameConstants.CENTER_ANCHOR);
        }
      }
    }
  }

  private void drawUserInfo(Graphics g) {
    if (userInfoLocation == null) {
      return;
    }
    
    for (int i = 0; i < tableUsers.size(); i++) {
      int index = getRealIndex(i);
      if ((index < isUserLeave.len()) && !isUserLeave.array[index]) {
        DrawUtils.drawUserInfo(g, ((User) tableUsers.elementAt(index)).getName(), userInfoLocation[i][0], userInfoLocation[i][1], isInfoRightToLeft[i]);
      }
    } 
  }

  private void drawPhom320x240(Graphics g) {
    if (phoms == null) {
      return;
    }
    
    if (numberOfPlayer == 2) {
      int index = getRealIndex(1);
      int size = phoms.array[index].size();
      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], GameConstants.SCREEN_WIDTH / 2, 15, GameConstants.TOP_HCENTER_ANCHOR);
      }
      for (int i = size - 1; i >= 0; i--) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(i);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 184 - j * CARD_DISTANCE, 80 - (size - i) * 18, GameConstants.BOTTOM_LEFT_ANCHOR, true);
        }
      }
    } else if (numberOfPlayer == 3) {
      int index = getRealIndex(1);
      int size = phoms.array[index].size();
      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], GameConstants.SCREEN_WIDTH / 2, 15, GameConstants.TOP_HCENTER_ANCHOR);
      }
      for (int i = size - 1; i >= 0; i--) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(i);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 184 - j * CARD_DISTANCE, 80 - (size - i) * 18, GameConstants.BOTTOM_LEFT_ANCHOR, true);
        }
      }
      
      index = getRealIndex(2);
      size = phoms.array[index].size();
      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], 15, GameConstants.SCREEN_HEIGHT / 2, GameConstants.VCENTER_LEFT_ANCHOR);
      }
      for (int i = 0; i < size; i++) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(i);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 30 + CARD_DISTANCE * j, 70 + 18 * i, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }
    } else if (numberOfPlayer == 4) {
      int index = getRealIndex(1);
      int size = phoms.array[index].size();
      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], GameConstants.SCREEN_WIDTH - 15, GameConstants.SCREEN_HEIGHT / 2, GameConstants.VCENTER_RIGHT_ANCHOR);
      }
      for (int i = 0; i < size; i++) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(i);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 234 + CARD_DISTANCE * j, 70 + 18 * i, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }

      index = getRealIndex(2);
      size = phoms.array[index].size();
      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], GameConstants.SCREEN_WIDTH / 2, 15, GameConstants.TOP_HCENTER_ANCHOR);
      }
      for (int i = size - 1; i >= 0; i--) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(i);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 184 - j * CARD_DISTANCE, 80 - (size - i) * 18, GameConstants.BOTTOM_LEFT_ANCHOR, true);
        }
      }

      index = getRealIndex(3);
      size = phoms.array[index].size();
      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], 15, GameConstants.SCREEN_HEIGHT / 2, GameConstants.VCENTER_LEFT_ANCHOR);
      }
      for (int i = 0; i < phoms.array[index].size(); i++) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(i);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 30 + CARD_DISTANCE * j, 70 + 18 * i, GameConstants.TOP_LEFT_ANCHOR, true);
        }
      }
    }

    int size = phoms.array[myIndex].size();
    if (size == 0 && isHaphom.array[myIndex] && (timeDisplayMom[myIndex] < 50)) {
      g.drawImage(ketQuaImage[0], GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT - 45, GameConstants.BOTTOM_HCENTER_ANCHOR);
    }
    for (int i = 0; i < size; i++) {
      PhomInfo phom = (PhomInfo) phoms.array[myIndex].elementAt(i);
      for (int j = 0; j < phom.size(); j++) {
        drawCardImage(g, phom.getCard(j), 118 + j * CARD_DISTANCE, 150 + 20 * i, GameConstants.TOP_LEFT_ANCHOR, false);
      }
    }
  }

  private void drawPhom(Graphics g) {
    if (phoms == null) {
      return;
    }
    
    if (numberOfPlayer == 2) {
      int index = getRealIndex(1); // lấy index của người còn lại
      int size = phoms.array[index].size();
      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], GameConstants.SCREEN_WIDTH / 2, 15, GameConstants.TOP_HCENTER_ANCHOR);
      }
      if (size > 2) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(2);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 123 - j * CARD_DISTANCE, 80, GameConstants.BOTTOM_LEFT_ANCHOR, true);
        }
      }
      if (size > 1) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(1);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 123 - j * CARD_DISTANCE, 60, GameConstants.BOTTOM_LEFT_ANCHOR, true);
        }
      }
      if (size > 0) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(0);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 123 - j * CARD_DISTANCE, 40, GameConstants.BOTTOM_LEFT_ANCHOR, true);
        }
      }
    } else if (numberOfPlayer == 3) {// có 3 người chơi
      int index = getRealIndex(1);// người thứ 2
      int size = phoms.array[index].size();
      // Móm
      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], GameConstants.SCREEN_WIDTH / 2, 15, GameConstants.TOP_HCENTER_ANCHOR);
      }
      // Phỏm thứ nhất
      if (size > 2) {
        PhomInfo phom0 = (PhomInfo) phoms.array[index].elementAt(2);
        for (int j = 0; j < phom0.size(); j++) {
          drawCardImage(g, phom0.getCard(j), 123 - j * CARD_DISTANCE, 80, GameConstants.BOTTOM_LEFT_ANCHOR, true);
        }
      }
      if (size > 1) {
        PhomInfo phom0 = (PhomInfo) phoms.array[index].elementAt(1);
        for (int j = 0; j < phom0.size(); j++) {
          drawCardImage(g, phom0.getCard(j), 123 - j * CARD_DISTANCE, 60, GameConstants.BOTTOM_LEFT_ANCHOR, true);
        }
      }
      if (size > 0) {
        PhomInfo phom0 = (PhomInfo) phoms.array[index].elementAt(0);
        for (int j = 0; j < phom0.size(); j++) {
          drawCardImage(g, phom0.getCard(j), 123 - j * CARD_DISTANCE, 40, GameConstants.BOTTOM_LEFT_ANCHOR, true);
        }
      }

      index = getRealIndex(2); // người thứ 3
      size = phoms.array[index].size();

      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], 15, GameConstants.SCREEN_HEIGHT / 2, GameConstants.VCENTER_LEFT_ANCHOR);
      }
      for (int i = 0; i < size; i++) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(i);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 20 + CARD_DISTANCE * j, 116 + 20 * i, GameConstants.TOP_LEFT_ANCHOR, true);
        }
      }
    } else if (numberOfPlayer == 4) {
      int index = getRealIndex(1);
      int size = phoms.array[index].size();
      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], GameConstants.SCREEN_WIDTH - 15, GameConstants.SCREEN_HEIGHT / 2, GameConstants.VCENTER_RIGHT_ANCHOR);
      }

      for (int i = size - 1; i >= 0; i--) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(i);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 160 + CARD_DISTANCE * j, 116 + 18 * (size - i), GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }

      index = getRealIndex(2);
      size = phoms.array[index].size();

      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], GameConstants.SCREEN_WIDTH / 2, 15, GameConstants.TOP_HCENTER_ANCHOR);
      }
      for (int i = size - 1; i >= 0; i--) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(i);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 140 - j * CARD_DISTANCE, 84 - (phoms.array[index].size() - i) * 20, GameConstants.BOTTOM_LEFT_ANCHOR, true);
        }
      }

      index = getRealIndex(3);
      size = phoms.array[index].size();
      if (size == 0 && isHaphom.array[index] && (timeDisplayMom[index] < 50)) {
        g.drawImage(ketQuaImage[0], 15, GameConstants.SCREEN_HEIGHT / 2, GameConstants.VCENTER_LEFT_ANCHOR);
      }
      for (int i = 0; i < phoms.array[index].size(); i++) {
        PhomInfo phom = (PhomInfo) phoms.array[index].elementAt(i);
        for (int j = 0; j < phom.size(); j++) {
          drawCardImage(g, phom.getCard(j), 20 + CARD_DISTANCE * j, 116 + 20 * i, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }
    }
    int size = phoms.array[myIndex].size();
    if (size == 0 && isHaphom.array[myIndex] && (timeDisplayMom[myIndex] < 50)) {
      g.drawImage(ketQuaImage[0], GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT - 45, GameConstants.BOTTOM_LEFT_ANCHOR);
    }
    for (int i = 0; i < size; i++) {
      PhomInfo phom = (PhomInfo) phoms.array[myIndex].elementAt(i);
      for (int j = 0; j < phom.size(); j++) {
        drawCardImage(g, phom.getCard(j), 95 + j * CARD_DISTANCE, 206 + 20 * i, GameConstants.TOP_LEFT_ANCHOR, false);
      }
    }
  }

  private void drawUserCards(Graphics g, int[][] timeLocation) {
    if (userCards == null) {
      return;
    }
    
    if (numberOfPlayer == 2) {
      int index = getRealIndex(1);
      if (!isUserLeave.array[index] && userCards.array[index].size() > 0) {
        if (isShowUserCard.array[index] && !isSomeOneU) { // kết quả cuối ván, các quân bài còn lại
          for (int i = 0; i < userCards.array[index].size(); i++) {
            int cardValue = getInt(userCards.array[index], i);
            int cardX = (GameConstants.SCREEN_WIDTH - userCards.array[index].size() * CARD_DISTANCE - 55) / 2 + (userCards.array[index].size() - i) * CARD_DISTANCE;
            drawCardImage(g, cardValue, cardX, 20, GameConstants.BOTTOM_LEFT_ANCHOR, true);
          }
        } else {
          g.drawImage(baiUpImage, (GameConstants.SCREEN_WIDTH - gotCards.array[index].size() * CARD_DISTANCE - 55) / 2, 20, GameConstants.BOTTOM_LEFT_ANCHOR);
          if (!isHaphom.array[index]) {
            for (int i = 0; i < gotCards.array[index].size(); i++) {// các quân ăn
              int cardValue = getInt(gotCards.array[index], i);
              int cardX = (GameConstants.SCREEN_WIDTH - gotCards.array[index].size() * CARD_DISTANCE - 55) / 2 + (gotCards.array[index].size() - i) * CARD_DISTANCE;
              drawCardImage(g, cardValue, cardX, 30, GameConstants.BOTTOM_LEFT_ANCHOR, true);
            }
          }
        }
      }
    } else if (numberOfPlayer == 3) {
      int index = getRealIndex(1);
      if (!isUserLeave.array[index] && userCards.array[index].size() > 0) {
        if (isShowUserCard.array[index] && !isSomeOneU) {
          for (int i = 0; i < userCards.array[index].size(); i++) {
            int cardValue = getInt(userCards.array[index], i);
            int cardX = (GameConstants.SCREEN_WIDTH - userCards.array[index].size() * CARD_DISTANCE - 55) / 2 + (userCards.array[index].size() - i) * CARD_DISTANCE;
            drawCardImage(g, cardValue, cardX, 20, GameConstants.BOTTOM_LEFT_ANCHOR, true);
          }
        } else {
          g.drawImage(baiUpImage, (GameConstants.SCREEN_WIDTH - gotCards.array[index].size() * CARD_DISTANCE - 55) / 2, 20, GameConstants.BOTTOM_LEFT_ANCHOR);
          if (!isHaphom.array[index]) {
            for (int i = 0; i < gotCards.array[index].size(); i++) {
              int cardValue = getInt(gotCards.array[index], i);
              int cardX = (GameConstants.SCREEN_WIDTH - gotCards.array[index].size() * CARD_DISTANCE - 55) / 2 + (gotCards.array[index].size() - i) * CARD_DISTANCE;
              drawCardImage(g, cardValue, cardX, 30, GameConstants.BOTTOM_LEFT_ANCHOR, false);
            }
          }
        }
      }
      
      index = getRealIndex(2);
      if (!isUserLeave.array[index] && userCards.array[index].size() > 0) {
        if (isShowUserCard.array[index] && !isSomeOneU) {
          for (int i = 0; i < userCards.array[index].size(); i++) {
            int cardValue = getInt(userCards.array[index], i);
            int cardY = (GameConstants.SCREEN_HEIGHT - userCards.array[index].size() * CARD_DISTANCE - 72) / 2 + (userCards.array[index].size() - i) * CARD_DISTANCE;
            drawCardImage(g, cardValue, 15, cardY, GameConstants.TOP_RIGHT_ANCHOR, false);
          }
        } else {
          g.drawImage(baiUpImage, 15, (GameConstants.SCREEN_HEIGHT - gotCards.array[index].size() * CARD_DISTANCE - 72) / 2, GameConstants.TOP_RIGHT_ANCHOR);
          if (!isHaphom.array[index]) {
            for (int i = 0; i < gotCards.array[index].size(); i++) {
              int cardValue = getInt(gotCards.array[index], i);
              int cardY = (GameConstants.SCREEN_HEIGHT - gotCards.array[index].size() * CARD_DISTANCE - 72) / 2 + (gotCards.array[index].size() - i) * CARD_DISTANCE;
              drawRotate90CardImage(g, cardValue, 30, cardY, GameConstants.TOP_RIGHT_ANCHOR);
            }
          }
        }
      }
    } else if (numberOfPlayer == 4) {
      int index = getRealIndex(1);
      if (!isUserLeave.array[index] && userCards.array[index].size() > 0) {
        if (isShowUserCard.array[index] && !isSomeOneU) {
          for (int i = 0; i < userCards.array[index].size(); i++) {
            int cardValue = getInt(userCards.array[index], i);
            int cardY = (GameConstants.SCREEN_HEIGHT - userCards.array[index].size() * CARD_DISTANCE - 72) / 2 + i * CARD_DISTANCE;
            drawCardImage(g, cardValue, GameConstants.SCREEN_WIDTH - 22, cardY, GameConstants.TOP_LEFT_ANCHOR, false);
          }
        } else {
          g.drawImage(baiUpImage, GameConstants.SCREEN_WIDTH - 22, (GameConstants.SCREEN_HEIGHT - gotCards.array[index].size() * CARD_DISTANCE - 72) / 2, GameConstants.TOP_LEFT_ANCHOR);
          if (!isHaphom.array[index]) {
            for (int i = 0; i < gotCards.array[index].size(); i++) {
              int cardValue = getInt(gotCards.array[index], i);
              int cardY = (GameConstants.SCREEN_HEIGHT - gotCards.array[index].size() * CARD_DISTANCE - 72) / 2 + (i + gotCards.array[index].size()) * CARD_DISTANCE;
              drawRotate90CardImage(g, cardValue, GameConstants.SCREEN_WIDTH - 30, cardY, GameConstants.TOP_LEFT_ANCHOR);
            }
          }
        }
      }

      index = getRealIndex(2);
      if (!isUserLeave.array[index] && userCards.array[index].size() > 0) {
        if (isShowUserCard.array[index] && !isSomeOneU) {
          for (int i = 0; i < userCards.array[index].size(); i++) {
            int cardValue = getInt(userCards.array[index], i);
            int cardX = (GameConstants.SCREEN_WIDTH - userCards.array[index].size() * CARD_DISTANCE - 55) / 2 + (userCards.array[index].size() - i) * CARD_DISTANCE;
            drawCardImage(g, cardValue, cardX, 20, GameConstants.BOTTOM_LEFT_ANCHOR, true);
          }
        } else {
          g.drawImage(baiUpImage, (GameConstants.SCREEN_WIDTH - gotCards.array[index].size() * CARD_DISTANCE - 55) / 2, 20, GameConstants.BOTTOM_LEFT_ANCHOR);
          if (!isHaphom.array[index]) {
            for (int i = 0; i < gotCards.array[index].size(); i++) {
              int cardValue = getInt(gotCards.array[index], i);
              int cardX = (GameConstants.SCREEN_WIDTH - gotCards.array[index].size() * CARD_DISTANCE - 55) / 2 + (gotCards.array[index].size() - i) * CARD_DISTANCE;
              drawCardImage(g, cardValue, cardX, 30, GameConstants.BOTTOM_LEFT_ANCHOR, true);
            }
          }
        }
      }
      
      index = getRealIndex(3);
      if (!isUserLeave.array[index] && userCards.array[index].size() > 0) {
        if (isShowUserCard.array[index] && !isSomeOneU) {
          for (int i = 0; i < userCards.array[index].size(); i++) {
            int cardValue = getInt(userCards.array[index], i);
            int cardY = (GameConstants.SCREEN_HEIGHT - userCards.array[index].size() * CARD_DISTANCE - 72) / 2 + (userCards.array[index].size() - i) * CARD_DISTANCE;
            drawCardImage(g, cardValue, 22, cardY, GameConstants.TOP_RIGHT_ANCHOR, false);
          }
        } else {
          g.drawImage(baiUpImage, 22, (GameConstants.SCREEN_HEIGHT - gotCards.array[index].size() * CARD_DISTANCE - 72) / 2, GameConstants.TOP_RIGHT_ANCHOR);
          if (!isHaphom.array[index]) {
            for (int i = 0; i < gotCards.array[index].size(); i++) {
              int cardValue = getInt(gotCards.array[index], i);
              int cardY = (GameConstants.SCREEN_HEIGHT - gotCards.array[index].size() * CARD_DISTANCE - 72) / 2 + (gotCards.array[index].size() - i) * CARD_DISTANCE;
              drawRotate90CardImage(g, cardValue, 30, cardY, GameConstants.TOP_RIGHT_ANCHOR);
            }
          }
        }
      }
    }
    
    if (isViewUser) {
      return;
    }

    int userCardSize = userCards.array[myIndex].size();
    for (int i = 0; i < userCardSize; i++) {
      int cardValue = getInt(userCards.array[myIndex], i);
      int cardX = GameConstants.SCREEN_WIDTH / 2 - (userCardSize * CARD_DISTANCE) / 2 + i * CARD_DISTANCE;
      int cardY = GameConstants.SCREEN_HEIGHT - 49;
      if (getIndexByValue(selectedCardByUser, cardValue) > -1) {
        cardY -= 22;
        drawCardImage(g, cardValue, cardX, cardY, GameConstants.TOP_LEFT_ANCHOR, false);
      } else if (getIndexByValue(gotCards.array[myIndex], cardValue) > -1) {
        drawCardImage(g, cardValue, cardX, cardY, GameConstants.TOP_LEFT_ANCHOR, false);
        g.setColor(0x00FF00);
        g.drawRoundRect(cardX + 2, cardY + 1, 28, 45, 7, 7);
        g.drawRoundRect(cardX + 3, cardY + 2, 26, 43, 7, 7);
      } else {
        if (i == movePointer) {
          if (isCardsChange) {
            drawCardImage(g, cardValue, cardX, cardY + 8, GameConstants.TOP_LEFT_ANCHOR, false);
          } else {
            drawCardImage(g, cardValue, cardX, cardY, GameConstants.TOP_LEFT_ANCHOR, false);
          }
        } else {
          drawCardImage(g, cardValue, cardX, cardY, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }
    }

    // Đếm thời gian của người chơi hiện tại
    if (currentTimeCount > -1) {
      int index = getDrawIndex(currentTimeIndex);
      if (numberOfPlayer == 2) {
        if (index == 1) {
          index = 2;
        }
      } else if (numberOfPlayer == 3) {
        if (index > 0) {
          index++;
        }
      }
      g.drawImage(numberBgImage, timeLocation[index][0], timeLocation[index][1], GameConstants.CENTER_ANCHOR);
      text8.drawString2(g, String.valueOf(currentTimeCount), GameColor.WHITE_CODE, timeLocation[index][0], timeLocation[index][1], GameConstants.CENTER_ANCHOR);
    }

    // Draw poiter
    if (userCardSize > 0) {
      if (movePointer > userCards.array[myIndex].size() - 1) {
        movePointer = userCards.array[myIndex].size() - 1;
      }
      int card = NumberUtil.parseInt(String.valueOf(userCards.array[myIndex].elementAt(movePointer)));
      if (getIndexByValue(selectedCardByUser, card) == -1) {
        g.drawImage(pointerImage, GameConstants.SCREEN_WIDTH / 2 - (userCardSize * CARD_DISTANCE) / 2 + 10 + CARD_DISTANCE * movePointer, GameConstants.SCREEN_HEIGHT - 57, GameConstants.BOTTOM_HCENTER_ANCHOR);
      } else {
        g.drawImage(pointerImage, GameConstants.SCREEN_WIDTH / 2 - (userCardSize * CARD_DISTANCE) / 2 + 10 + CARD_DISTANCE * movePointer, GameConstants.SCREEN_HEIGHT - 77, GameConstants.BOTTOM_HCENTER_ANCHOR);
      }
    }
  }

  private void drawCommand(Graphics g) {
    if (state == HA_PHOM_STATE) {
      DrawUtils.setBottomBar(_manager, "", "Hạ phỏm", "Menu");
    } else if (state == GET_CARD_STATE) {
      DrawUtils.setBottomBar(_manager, "Bốc", "Ăn", "Menu");
    } else if (state == FIRE_CARD_STATE && !isShowingFinalResult) {
      if (isGuiBai) {
        DrawUtils.setBottomBar(_manager, "Gửi bài", "Đánh", "Menu");
      } else {
        DrawUtils.setBottomBar(_manager, "", "Đánh", "Menu");
      }
    } else {
      DrawUtils.setBottomBar(_manager, "", "", "Menu");
    }
    
    g.setColor(GameColor.WHITE_CODE);
    if (isShowingFinalResult) {
      DrawUtils.setBottomBar(_manager, "", "Chơi tiếp", "Thoát");
    }
  }

  private void drawFiredCard320x240(Graphics g) {
    if (firedCards == null || isShowingFinalResult) {
      return;
    }
    
    if (numberOfPlayer == 2) {
      int index = getRealIndex(1);
      if (!isUserLeave.array[index]) {
        for (int i = 0; i < firedCards.array[index].size(); i++) {
          int value = getInt(firedCards.array[index], i);
          drawCardImage(g, value, 55 + i * FIRED_CARD_DISTANCE, 33, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }

      int x = 234 - firedCards.array[myIndex].size() * FIRED_CARD_DISTANCE;
      for (int i = 0; i < firedCards.array[myIndex].size(); i++) {
        int value = getInt(firedCards.array[myIndex], i);
        drawCardImage(g, value, x + i * FIRED_CARD_DISTANCE, 180, GameConstants.BOTTOM_LEFT_ANCHOR, false);
      }
    } else if (numberOfPlayer == 3) {
      int index = getRealIndex(2);
      if (!isUserLeave.array[index]) {
        for (int i = firedCards.array[index].size() - 1; i >= 0 ; i--) {
          int value = getInt(firedCards.array[index], firedCards.array[index].size() - 1 - i);
          drawCardImage(g, value, 55 + i * FIRED_CARD_DISTANCE, 180, GameConstants.BOTTOM_LEFT_ANCHOR, false);
        }
      }
      
      index = getRealIndex(1);
      if (!isUserLeave.array[index]) {
        for (int i = firedCards.array[index].size() - 1; i >= 0 ; i--) {
          int value = getInt(firedCards.array[index], firedCards.array[index].size() - 1 - i);
          drawCardImage(g, value, 55 + i * FIRED_CARD_DISTANCE, 33, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }

      int x = 234 - firedCards.array[myIndex].size() * FIRED_CARD_DISTANCE;
      for (int i = 0; i < firedCards.array[myIndex].size(); i++) {
        int value = getInt(firedCards.array[myIndex], i);
        drawCardImage(g, value, x + i * FIRED_CARD_DISTANCE, 180, GameConstants.BOTTOM_LEFT_ANCHOR, false);
      }
    } else if (numberOfPlayer == 4) {
      int index = getRealIndex(1);
      if (!isUserLeave.array[index]) {
        int x = 234 - firedCards.array[index].size() * FIRED_CARD_DISTANCE;
        for (int i = 0; i < firedCards.array[index].size(); i++) {
          int value = getInt(firedCards.array[index], i);
          drawCardImage(g, value, x + i * FIRED_CARD_DISTANCE, 33, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }
      
      index = getRealIndex(2);
      if (!isUserLeave.array[index]) {
        for (int i = firedCards.array[index].size() - 1; i >= 0 ; i--) {
          int value = getInt(firedCards.array[index], firedCards.array[index].size() - 1 - i);
          drawCardImage(g, value, 55 + i * FIRED_CARD_DISTANCE, 33, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }

      index = getRealIndex(3);
      if (!isUserLeave.array[index]) {
        for (int i = firedCards.array[index].size() - 1; i >= 0 ; i--) {
          int value = getInt(firedCards.array[index], firedCards.array[index].size() - 1 - i);
          drawCardImage(g, value, 55 + i * FIRED_CARD_DISTANCE, 180, GameConstants.BOTTOM_LEFT_ANCHOR, false);
        }
      }

      _x = 234 - firedCards.array[myIndex].size() * FIRED_CARD_DISTANCE;
      for (int i = 0; i < firedCards.array[myIndex].size(); i++) {
        int value = getInt(firedCards.array[myIndex], i);
        drawCardImage(g, value, _x + i * FIRED_CARD_DISTANCE, 180, GameConstants.BOTTOM_LEFT_ANCHOR, false);
      }
    }
  }

  private void drawFiredCard(Graphics g) {
    if (firedCards == null || isShowingFinalResult) {
      return;
    }
    
    if (numberOfPlayer == 2) {
      int index = getRealIndex(1);
      if (!isUserLeave.array[index]) {
        for (int i = 0; i < firedCards.array[index].size(); i++) {
          int value = getInt(firedCards.array[index], i);
          drawCardImage(g, value, 30 + i * FIRED_CARD_DISTANCE, 55, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }

      int x = 170 - firedCards.array[myIndex].size() * FIRED_CARD_DISTANCE;
      for (int i = 0; i < firedCards.array[myIndex].size(); i++) {
        int value = getInt(firedCards.array[myIndex], i);
        drawCardImage(g, value, x + i * FIRED_CARD_DISTANCE, 233, GameConstants.BOTTOM_LEFT_ANCHOR, false);
      }
    } else if (numberOfPlayer == 3) {
      int index = getRealIndex(2);
      if (!isUserLeave.array[index]) {
        for (int i = firedCards.array[index].size() - 1; i >= 0 ; i--) {
          int value = getInt(firedCards.array[index], firedCards.array[index].size() - 1 - i);
          drawCardImage(g, value, 25 + i * FIRED_CARD_DISTANCE, 233, GameConstants.BOTTOM_LEFT_ANCHOR, false);
        }
      }
      
      index = getRealIndex(1);
      if (!isUserLeave.array[index]) {
        for (int i = firedCards.array[index].size() - 1; i >= 0 ; i--) {
          int value = getInt(firedCards.array[index], firedCards.array[index].size() - 1 - i);
          drawCardImage(g, value, 25 + i * FIRED_CARD_DISTANCE, 55, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }

      int x = 175 - firedCards.array[myIndex].size() * FIRED_CARD_DISTANCE;
      for (int i = 0; i < firedCards.array[myIndex].size(); i++) {
        int value = getInt(firedCards.array[myIndex], i);
        drawCardImage(g, value, x + i * FIRED_CARD_DISTANCE, 233, GameConstants.BOTTOM_LEFT_ANCHOR, false);
      }
    } else if (numberOfPlayer == 4) {
      int index = getRealIndex(1);
      if (!isUserLeave.array[index]) {
        int x = 175 - firedCards.array[index].size() * FIRED_CARD_DISTANCE;
        for (int i = 0; i < firedCards.array[index].size(); i++) {
          int value = getInt(firedCards.array[index], i);
          drawCardImage(g, value, x + i * FIRED_CARD_DISTANCE, 55, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }
      
      index = getRealIndex(2);
      if (!isUserLeave.array[index]) {
        for (int i = firedCards.array[index].size() - 1; i >= 0 ; i--) {
          int value = getInt(firedCards.array[index], firedCards.array[index].size() - 1 - i);
          drawCardImage(g, value, 25 + i * FIRED_CARD_DISTANCE, 55, GameConstants.TOP_LEFT_ANCHOR, false);
        }
      }

      index = getRealIndex(3);
      if (!isUserLeave.array[index]) {
        for (int i = firedCards.array[index].size() - 1; i >= 0 ; i--) {
          int value = getInt(firedCards.array[index], firedCards.array[index].size() - 1 - i);
          drawCardImage(g, value, 25 + i * FIRED_CARD_DISTANCE, 233, GameConstants.BOTTOM_LEFT_ANCHOR, false);
        }
      }

      _x = 175 - firedCards.array[myIndex].size() * FIRED_CARD_DISTANCE;
      for (int i = 0; i < firedCards.array[myIndex].size(); i++) {
        int value = getInt(firedCards.array[myIndex], i);
        drawCardImage(g, value, _x + i * FIRED_CARD_DISTANCE, 233, GameConstants.BOTTOM_LEFT_ANCHOR, false);
      }
    }
  }

  private void drawMessage(Graphics g) {
    g.setColor(0xFFA500);
    if (messageIndex > -1) {
      g.fillRoundRect(GameConstants.SCREEN_WIDTH / 2 - 80, GameConstants.SCREEN_HEIGHT / 2 - 22, 160, 24, 5, 5);
    }
    switch (messageIndex) {
    case 0:
      text8.drawString2(g, "Bài ăn không hợp lệ", GameColor.WHITE_CODE, GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT / 2 - 20, GameConstants.TOP_HCENTER_ANCHOR);
      break;
    case 1:
      text8.drawString2(g, "Bài đánh không hợp lệ", GameColor.WHITE_CODE, GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT / 2 - 20, GameConstants.TOP_HCENTER_ANCHOR);
      break;
    case 2:
      text8.drawString2(g, "Hạ bài", GameColor.WHITE_CODE, GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT / 2 - 20, GameConstants.TOP_HCENTER_ANCHOR);
      break;
    case 4:
      text8.drawString2(g, "Bạn phải chọn bài để ăn phỏm", GameColor.WHITE_CODE, GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT / 2 - 20, GameConstants.TOP_HCENTER_ANCHOR);
      break;
    case 5:
      text8.drawString2(g, "Bạn phải nhấc bài để đánh", GameColor.WHITE_CODE, GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT / 2 - 20, GameConstants.TOP_HCENTER_ANCHOR);
      break;
    case 6:
      text8.drawString2(g, "Phỏm hạ không hợp lệ", GameColor.WHITE_CODE, GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT / 2 - 20, GameConstants.TOP_HCENTER_ANCHOR);
      break;
    case 7:
      text8.drawString2(g, "Bài gửi không hợp lệ", GameColor.WHITE_CODE, GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT / 2 - 20, GameConstants.TOP_HCENTER_ANCHOR);
      break;
    }
  }
  
  private void drawMoneyChangeNotification(Graphics g) {
    if (moneyChangeIndex > 0) {
      g.setColor(0xFFA500);
      moneyChangeMessage = String.valueOf(moneyChangeMessage);
      int messageWidth = text8.stringWidth(moneyChangeMessage) + 3;
      g.fillRoundRect(GameConstants.SCREEN_WIDTH / 2 - messageWidth / 2, GameConstants.SCREEN_HEIGHT / 2 - 22, messageWidth, 24, 5, 5);
      text8.drawString2(g, moneyChangeMessage, GameColor.WHITE_CODE, GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT / 2 - 20, GameConstants.TOP_HCENTER_ANCHOR);
    }
  }

  private void drawCardImage(Graphics g, int quanBai, int x, int y, int anchor, boolean isRotate180) {
    if (!isRotate180) {
      g.drawImage(getCard(quanBai), x, y, anchor);
    } else {
      GameImage cardImage = (GameImage) rotatedCardCache.get(new Integer(quanBai));
      if (cardImage == null) {
        cardImage = getCard(quanBai);
        cardImage = ImageUtil.rotate(cardImage, 180);
        rotatedCardCache.put(new Integer(quanBai), cardImage);
      }
      g.drawImage(cardImage, x, y, anchor);
    }
  }
  
  private void drawRotate90CardImage(Graphics g, int quanBai, int x, int y, int anchor) {
    GameImage cardImage = (GameImage) rotated90CardCache.get(new Integer(quanBai));
    if (cardImage == null) {
      cardImage = getCard(quanBai);
      cardImage = ImageUtil.rotate(cardImage, 90);
      rotated90CardCache.put(new Integer(quanBai), cardImage);
    }
    g.drawImage(cardImage, x, y, anchor);
  }
  
  private GameImage getCard(int quanBai) {
    if (cardImges[quanBai] == null) {
for1: for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 13; j++) {
          int index = i * 13 + j;
          if (quanBai != index) {
            continue;
          }
          cardImges[index] = ImageUtil.getImage(Constants.CARD_IMAGE_CATEGORY, (j + 1) + "_" + cardOrder[i] + ".png");
          break for1;
        }
      }
    }
    return cardImges[quanBai];
  }
  
  private void sapXepTangDanTheoCaNgang(Vector cards) {
    if (cards == null) {
      return;
    }
    for (int i = 0; i < cards.size() - 1; i++) {
      for (int j = i + 1; j < cards.size(); j++) {
        Object info = cards.elementAt(i);
        Object infoTemp = cards.elementAt(j);
        if (NumberUtil.parseInt(info.toString()) % 13 > NumberUtil.parseInt(infoTemp.toString()) % 13) {
          cards.setElementAt(infoTemp, i);
          cards.setElementAt(info, j);
        }
      }
    }
  }

  public void alertEventPerform(int alertType, int eventType, int alertId) {
    if (alertId == 99) { // Thoát và quay trở về room
      GameGlobal.nextState(FrmGroupTableFreeUserFriend.instance(), null);
    } else if (alertId == 98) {
      if (eventType == GameAlert.YES_BUTTON) {
        state = FIRE_CARD_STATE;
        currentTurn++;
      }
    } else if (alertId == 97) {
      if (eventType == GameAlert.YES_BUTTON) {
        SocketClientUtil.leaveTableRequest();
        GameGlobal.nextState(FrmGroupListTableFreeUserChat.instance(), null);
      }
    }
  }

  private boolean isCaDoc(Vector quanBais) {
    quanBais = VerticalSort(quanBais);
    int quanBaiLen = quanBais.size();
    if (quanBaiLen <= 2) {
      return false;
    }
    for (int i = 0; i < quanBaiLen - 1; i++) {
      if (Math.abs(NumberUtil.parseInt(quanBais.elementAt(i + 1).toString()) - NumberUtil.parseInt(quanBais.elementAt(i).toString())) != 1) {
        return false;
      }
    }
    if ((NumberUtil.parseInt(quanBais.firstElement().toString()) / 13 != NumberUtil.parseInt(quanBais.lastElement().toString()) / 13)) {
      return false;
    }
    return true;
  }

  private boolean isCaNgang(Vector quanBais, int quanBai) {
    quanBais.addElement(new Integer(quanBai));
    int quanBaiLen = quanBais.size();
    if (quanBaiLen <= 2) {
      return false;
    }
    for (int i = 0; i < quanBaiLen - 1; i++) {
      if (NumberUtil.parseInt(quanBais.elementAt(i).toString()) % 13 != (NumberUtil.parseInt(quanBais.elementAt(i + 1).toString()) % 13)) {
        return false;
      }
    }
    return true;
  }

  private Vector VerticalSort(Vector cards) {
    if (cards == null) {
      return null;
    }
    int size = cards.size();
    for (int i = 0; i < size - 1; i++) {
      for (int j = i + 1; j < size; j++) {
        int info = NumberUtil.parseInt(cards.elementAt(i).toString());
        int infoTemp = NumberUtil.parseInt(cards.elementAt(j).toString());
        if (info > infoTemp) {
          cards.setElementAt(new Integer(infoTemp), i);
          cards.setElementAt(new Integer(info), j);
        }
      }
    }
    return cards;
  }

  public void destroy() {
    rotatedCardCache = null;
    rotated90CardCache = null;
    isInfoRightToLeft = null;
    userInfoLocation = null;
    timeDisplayMom = null;
    isHaphom = null;
    isUserLeave = null;
    tableImage = null;
    text8 = null;
    text11 = null;
    numberBgImage = null;
    userJidU = null;
    baiUpImage = null;
    pointerImage = null;
    cardImges = null;
    userCards = null;
    firedCards = null;
    gotCards = null;
    phoms = null;
    selectedCardByUser = null;
    cardOrder = null;

    ketQuaImage = null;
    nhatImage = null;
    uImage = null;
    isShowUserCard = null;
    belongToPhoms = null;
    cardPoint = null;
    tableUsers = null;
  }

  public void onActionPerform(Event event) {
    // "Chơi tiếp", "Sắp xếp", "Thoát"
    String action = event.getAction();
    if (action.equals("Sắp xếp")) { // Sắp xếp
      sapXepTangDanTheoCaNgang(userCards.array[myIndex]);
    } else if (action.equals("Thoát")) { // Thoát
      GameGlobal.alert.showAlert1(this, GameAlert.YES_NO_TYPE, StringArray.create1("Thoát ra sẽ bị tính là thua cuộc", "Bạn có muốn thoát?"), 97);
    }
  }

  public void onConnectDone() {
  }

  public void onConnectFail() {
  }

  public void onDisconnect() {
  }
}
